#include "logger.h"

#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

logger_setting_t *g_logger = NULL;

static
const char *get_log_level_message(int idx)
{
    static char *s_message[] = 
        {
            "NONE",
            "INFO",
            "DEBUG",
            "ERROR",
            "FATAL"
        };

    if (idx >= LOG_NONE && idx <= LOG_FATAL)
        return s_message[idx - LOG_NONE];
    return "";
}

static
int default_log_writer(logger_setting_t *pls, log_level_t ll, const char *fn, int line, const char *fnname, const char *fmt, ...)
{
    assert(pls != NULL);
        
    int iRetValue = 0;
    char acTempBuffer[1024];
    va_list ap;
    
    if (ll == LOG_NONE || ll < pls->level) return iRetValue;
    
    va_start(ap, fmt);
    vsprintf(acTempBuffer, fmt, ap);
    va_end(ap);

    iRetValue = fprintf(pls->filp, "[%s %s#%d@%s] %s", get_log_level_message(ll),
                        fn, line, fnname, acTempBuffer);
    return iRetValue;
}

logger_setting_t *get_default_logger()
{
    if (g_logger == NULL)
    {
        g_logger = logger_setting_init_fp(stdout, LOG_DEBUG, default_log_writer);
    }
    return g_logger;
}

void free_default_logger()
{
    logger_setting_free(g_logger);
}

logger_setting_t *logger_setting_init(const char *fn, log_level_t level, fn_log_writer log_writer)
{
    logger_setting_t *pls = (logger_setting_t *)malloc(sizeof(logger_setting_t));
    if (pls == NULL) return NULL;

    pls->filp = fopen(fn, "a");
    if (pls->filp == NULL)
    {
        free(pls);
        return NULL;
    }

    pls->level = level;
    pls->log_writer = log_writer;
    return pls;
}

logger_setting_t *logger_setting_init_fp(FILE *fp, log_level_t level, fn_log_writer log_writer)
{
    logger_setting_t *pls = (logger_setting_t *)malloc(sizeof(logger_setting_t));
    if (pls == NULL) return NULL;

    pls->filp = fp;
    pls->level = level;
    pls->log_writer = log_writer;

    return pls;
}

void logger_setting_free(logger_setting_t *pls)
{
    if (pls == NULL) return ;

    fclose(pls->filp);
    free(pls);
}

#ifdef TEST_LOGGER
int main(int argc, char *argv[])
{
    get_default_logger();
    LOGGER_NONE("This would not appear.\n", "xxx");
    LOGGER_INFO("This is show in level %s.\n", "INFO");
    LOGGER_DEBUG("This is show in level %s.\n", "DEBUG");
    LOGGER_ERROR("This is show in level %s.\n", "ERROR");
    LOGGER_FATAL("This is show in level %s.\n", "FATAL");
    free_default_logger();
    return 0;
}
#endif

